package services

import (
    "github.com/beego/beego/v2/core/logs"
    "volux/utils"
    "fmt"
)

type RecoveryService struct {
    storageService *StorageService
    spdkClient     *utils.SPDKClient
}

func NewRecoveryService(storage *StorageService, spdk *utils.SPDKClient) *RecoveryService {
    return &RecoveryService{
        storageService: storage,
        spdkClient:     spdk,
    }
}

// RecoverResources 从etcd恢复所有资源
func (r *RecoveryService) RecoverResources() error {
    // 1. 恢复Bdevs
    bdevs, err := r.storageService.GetBdevs()
    if err != nil {
        return err
    }
    
    for _, bdev := range bdevs {
        if err := r.recoverBdev(bdev); err != nil {
            logs.Error("Failed to recover bdev: %v", err)
        }
    }
    
    // 2. 恢复Subsystems
    subsystems, err := r.storageService.GetSubsystems()
    if err != nil {
        return err
    }
    
    for _, subsystem := range subsystems {
        if err := r.recoverSubsystem(subsystem); err != nil {
            logs.Error("Failed to recover subsystem: %v", err)
        }
    }
    
    return nil
}

func (r *RecoveryService) recoverBdev(bdev interface{}) error {
    bdevMap := bdev.(map[string]interface{})
    bdevType := bdevMap["type"].(string)
    
    switch bdevType {
    case "malloc":
        // 修正类型转换
        sizeMB := int64(bdevMap["size_mb"].(float64))
        return r.spdkClient.CreateMallocBdev(
            bdevMap["name"].(string),
            int(sizeMB), // 修改类型转换
        )
    case "aio":
        return r.spdkClient.CreateAioBdev(
            bdevMap["name"].(string),
            bdevMap["filename"].(string),
        )
    case "nvme":
        return r.spdkClient.CreateNVMeBdev(
            bdevMap["name"].(string),
            bdevMap["traddr"].(string),
            bdevMap["transport"].(string),
        )
    default:
        return fmt.Errorf("unsupported bdev type: %s", bdevType)
    }
}

func (r *RecoveryService) restoreBdev(bdevMap map[string]interface{}) error {
    sizeMB := int64(bdevMap["size_mb"].(float64))  // 修改类型转换
    return r.spdkClient.CreateMallocBdev(bdevMap["name"].(string), int(sizeMB)) // 修改类型转换
}

func (r *RecoveryService) recoverSubsystem(subsystem interface{}) error {
    sub := subsystem.(map[string]interface{})
    
    // 1. 创建子系统
    err := r.spdkClient.CreateNVMFSubsystem(
        sub["nqn"].(string),
        sub["serial_number"].(string),
        sub["allow_any_host"].(bool),
        convertToStringSlice(sub["allowed_hosts"]),
    )
    if err != nil {
        return err
    }
    
    // 2. 恢复命名空间
    if namespaces, ok := sub["namespaces"].([]interface{}); ok {
        for _, ns := range namespaces {
            nsMap := ns.(map[string]interface{})
            err = r.spdkClient.AddNamespaceToSubsystem(
                sub["nqn"].(string),
                nsMap["bdev_name"].(string),
                uint32(nsMap["nsid"].(float64)),
                nsMap["nguid"].(string),
                nsMap["eui64"].(string),
            )
            if err != nil {
                return err
            }
        }
    }
    
    // 3. 恢复监听器
    if listeners, ok := sub["listeners"].([]interface{}); ok {
        for _, listener := range listeners {
            l := listener.(map[string]interface{})
            addr := l["address"].(map[string]interface{})
            err = r.spdkClient.AddNVMFListener(
                sub["nqn"].(string),
                addr["trtype"].(string),
                addr["traddr"].(string),
                uint16(addr["trsvcid"].(float64)),
            )
            if err != nil {
                return err
            }
        }
    }
    
    return nil
}

func convertToStringSlice(input interface{}) []string {
    if input == nil {
        return nil
    }
    
    inputSlice := input.([]interface{})
    result := make([]string, len(inputSlice))
    for i, v := range inputSlice {
        result[i] = v.(string)
    }
    return result
}
